home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
LIBRARY
/
MWCC03
/
MESSAGE.ZIP
/
MSGUNIT.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-08-18
|
27KB
|
855 lines
{**********************************************************************}
{* *}
{* Microworks Sample Application *}
{* *}
{* for Borland Pascal v7.0 and Turbo Pascal for Windows v1.5 *}
{* *}
{* Copyright 1992-93 Jeff Franks (Microworks) Sydney, Australia. *}
{* *}
{* You are free to use, modify, reproduce and distribute the *}
{* Sample Files (and/or any modified version) in any way you *}
{* find useful. *}
{* *}
{**********************************************************************}
{*** Introduction
Unit := MsgUnit
Files := Msgunit.pas
Units Required := MWCC.dll
Tabs := 2
Screen := 800 * 600
Date := August, 1993.
MsgUnit is the complete source code for the MWCC and SFX message boxes. It includes
the drawing, painting and keydown procedures from MWCC.dll (not found in MMsgBox.pas
in RTL.ZIP). I've included this source code as an example of how to write a non-OWL
application should the need arise - like in a DLL.
{*** About the Message Box unit
I rewrote to OWL MWCC and SFX message boxes from the previous version (in the MWCC unit in
MWCC02.ZIP) because I wanted to put the message boxes in MWCC.dll. Initially I rewrote
the message boxes using the DLLAPP.ZIP sample found in the BPascal forum's OWL library
(No 8). It worked great - 90% of the time, but every now and then I got a general
protection fault. The best I could do to trace the fault was to the behind the scenes
TWindowsObject.GetObjectPtr routine for the dummy DLLAPP Window. After weeks of hasle I
decided it would be quicker to rewrite the message boxes without Object Windows. One week
later and everything was working well. Best of all the exe files were about 4-5k smaller.
Then I hit another problem. You can't have multiple instances in a DLL. Because only one
instance of a dll is ever loaded, the second instance of an application that is run from
a DLL overwrites the data for the first instance. When you close the second instance your
left with the first instance and no data. This leaves you with is a window shell that
doesn't know what to do with itself.
I managed to find a multiple instance DLL that uses assembly code to keep a list of tasks.
Each new task that uses the DLL gets its own data segment. Unfortunaltely, it would have
taken too long to rewrite the message boxes a third time so I left that until the next
version.
MsgUnit imports the MWCC.dll procedures and functions it needs itself, so it doesn't need
MObjects.
One advantage of using generic Pascal programming to write a Windows program is that it
produces a smaller exe file.
When reading through the code everything is more or less upside down compared to an OWL
program because functions and procedures must be declared before they can be used. you might
find it easier to start at the bottom - at the MsgBoxWinMain procedure.
The code might look a little more complicated (or messy) because it is used to display two
different types of message boxes.
To use this unit compile it and then compile and run the Msgtest program.
I hope you find this unit useful.
Jeff...
***}
unit MsgUnit;
interface
uses WinProcs, WinTypes;
type
TMinMaxInfo = array [0..4] of TPoint;
PMinMaxInfo = ^TMinMaxInfo;
function MWCCMsgBox (WndParent: HWnd; ATxt, ACaption: PChar; ATextType: Word;
ABmp: PChar): Integer;
function SFXMsgBox (WndParent: HWnd; ATxt, ACaption: PChar; ATextType: Word): Integer;
function CreateDefaultFont (IsBold: Boolean): HFont;
procedure Draw3DBorder (Wnd: HWnd; X, Y, W, H: Integer; Shade: Word);
procedure DrawSFXFrame (Wnd: HWnd);
implementation
const
ctl_Recessed = 51;
ctl_Raised = 52;
var
Default1 : Boolean;
Default2 : Boolean;
Default3 : Boolean;
SFXStyle : Boolean;
BkBmp : HBitmap;
MsgBmp : HBitmap;
UpBmp1 : HBitmap;
UpBmp2 : HBitmap;
UpBmp3 : HBitmap;
BkBrush : HBrush;
LastWnd : HWnd;
MsgBoxWnd : HWnd;
WndButton1 : HWnd;
WndButton2 : HWnd;
WndButton3 : HWnd;
ID1 : Integer;
ID2 : Integer;
ID3 : Integer;
a : Integer;
b : Integer;
c : Integer;
d : Integer;
e : Integer;
f : Integer;
Reply : Integer;
ButtonProc1 : TFarProc;
ButtonProc2 : TFarProc;
ButtonProc3 : TFarProc;
OldProc1 : TFarProc;
OldProc2 : TFarProc;
OldProc3 : TFarProc;
HLib : THandle;
MWCCWndHdl : THandle;
SFXWndHdl : THandle;
WinRect : TRect;
TextType : Word;
szText : array[0..255] of Char;
szTitle : array[0..50] of Char;
function CreateDefaultFont; external 'MWCC' Index 1;
procedure Draw3DBorder; external 'MWCC' Index 5;
procedure DrawSFXFrame; external 'MWCC' Index 10;
procedure DrawMsgBoxButton (Wnd: HWnd; lParam: LongInt);
{*** From MWCC.dll
Draws the Message box buttons. It's a bit slow when launching the message box
because it loads each bitmap as it needs it. To overcome this the bitmaps that
need to be displayed initially (the up bitmaps) are loaded before the window is
constructed.
***}
var
Down : Boolean;
Up : Boolean;
Other : Boolean;
Bitmap : HBitmap;
MemDC : HDC;
Offset : Integer;
OldObject : THandle;
begin
with pDrawItemStruct(lParam)^, rcItem do
case CtlType of
odt_Button:
begin
if ItemAction = oda_Focus then exit;
Down := ((ItemAction and oda_Select) > 0) and ((ItemState and ods_Selected) > 0);
Up := ((ItemAction and oda_Select) > 0) and ((ItemState and ods_Selected) = 0);
Other := ((ItemAction and oda_Select) = 0) and ((ItemState and ods_Selected) = 0);
FillRect(HDC, rcItem, GetStockObject(LtGray_Brush));
Draw3DBorder(HWndItem, Left, Top, Right-Left, Bottom-Top, ctl_Recessed);
MemDC := CreateCompatibleDC(HDC);
if (GetFocus = HWndItem) then
begin
if Down then
OffSet := 3000
else
OffSet := 5000;
end
else
begin
if Down then
OffSet := 3000
else
if Up then
OffSet := 5000
else
if Other then
OffSet := 1000;
end;
Bitmap := LoadBitmap(HLib, PChar(OffSet + CtlID));
OldObject := SelectObject(MemDC, Bitmap);
BitBlt(HDC, Left, Top, Right-Left, Bottom-Top, MemDC, 0, 0, SrcCopy);
SelectObject(MemDC, OldObject);
DeleteObject(Bitmap);
DeleteDC(MemDC);
end;
end;
end;
procedure MsgBoxKeyDown (ParentWnd, Wnd: HWnd; wParam: Word);
{*** From MWCC.dll
MsgBoxKeyDown handles tabbing through the buttons. Because the message box is a window
and not a dialog tabbing doesn't automatically occur. EnableKBHandler can't be used here
because this is a non_OWL program.
***}
var
SibWnd : HWnd;
lStyle : LongInt;
ID : Word;
begin
SibWnd := 0;
ID := GetDlgCtrlID(Wnd);
case wParam of
vk_Return :
begin
SendMessage(MsgBoxWnd, wm_Command, ID, ID + bn_Clicked);
Exit;
end;
end;
while SibWnd = 0 do
begin
if ID = 7 then
ID := 1
else
ID := ID + 1;
SibWnd := GetDlgItem(MsgBoxWnd, ID);
lStyle := GetWindowLong (SibWnd, gwl_Style);
if not (lStyle = lStyle or ws_TabStop) then
SibWnd := 0;
end;
case wParam of
vk_Tab:
begin
SetFocus(SibWnd);
InvalidateRect(Wnd, nil, True);
InvalidateRect(SibWnd, nil, True);
end;
end;
end;
procedure PaintMsgBox (Wnd: HWnd; AText: PChar; Ofs1, Ofs2, Ofs3: Integer;
MsgBmp: HBitmap; SFXStyle: Boolean);
{*** From MWCC.dll
PaintMsgBox handles all the painting. It paints the window differently depending on whether
it's asn SFX message box (SFXStyle := true).
***}
var
OldBrush : HBrush;
NewBrush : HBrush;
MemDC : HDC;
PaintDC : HDC;
MsgFont : HFont;
OldObject : THandle;
PS : TPaintStruct;
CRect : TRect;
FRect : TRect;
W, H : Integer;
TextRect : TRect;
begin
BeginPaint(Wnd, PS);
PaintDC := GetDC(Wnd);
GetClientRect (Wnd, CRect);
with CRect do
begin
W := Right;
H := Bottom;
end;
if SFXStyle then
Draw3DBorder(Wnd, 23 - (Ofs2 div 2), 21, 342 + Ofs1 - (Ofs2 div 2), 98, ctl_Recessed)
else
begin
Draw3DBorder(Wnd, 1, 1, W-2, H-2, ctl_Raised);
Draw3DBorder(Wnd, 22, 22, 340 + Ofs1, 98, ctl_Recessed);
with FRect do
begin
Left := 23;
Top := 23;
Right := W-23;
Bottom := 119;
end;
FillRect(PaintDC, FRect, GetStockObject(LtGray_Brush));
end;
if MsgBmp <> 0 then
begin
MemDC := CreateCompatibleDC(PaintDC);
OldObject := SelectObject(MemDC, MsgBmp);
BitBlt(PaintDC, 30 - (Ofs2 div 2), 32 - Ofs3, 48, 64, MemDC, 0, 0, SrcCopy);
SelectObject(MemDC, OldObject);
DeleteDC(MemDC);
end;
with TextRect do
begin
Left := 84 - (Ofs2 div 2);
Top := 32 - Ofs3;
Right := 272 + Ofs1 - (Ofs2 div 2) + Left;
Bottom := 80 + Top;
end;
MsgFont := CreateDefaultFont(True);
SetBkMode(PaintDC, Transparent);
OldObject := SelectObject(PaintDC, MsgFont);
DrawText(PaintDC, AText, lStrLen(AText), TextRect, dt_Top or dt_Left or dt_WordBreak);
SelectObject(PaintDC, OldObject);
DeleteObject(MsgFont);
ReleaseDC(Wnd, PaintDC);
EndPaint(Wnd, PS);
end;
procedure InitializeData;
{*** Used to initialize all the data when the message box is created and destroyed ***}
begin
Default1 := False;
Default2 := False;
Default3 := False;
SFXStyle := False;
BkBmp := 0;
MsgBmp := 0;
UpBmp1 := 0;
UpBmp2 := 0;
UpBmp3 := 0;
BkBrush := 0;
LastWnd := 0;
MsgBoxWnd := 0;
WndButton1 := 0;
WndButton2 := 0;
WndButton3 := 0;
ID1 := 0;
ID2 := 0;
ID3 := 0;
a := 0;
b := 0;
c := 0;
d := 0;
e := 0;
f := 0;
ButtonProc1 := nil;
ButtonProc2 := nil;
ButtonProc3 := nil;
OldProc1 := nil;
OldProc2 := nil;
OldProc3 := nil;
HLib := 0;
MWCCWndHdl := 0;
SFXWndHdl := 0;
end;
function MsgBoxButton1Proc (Wnd: HWnd; Message, wParam: Word; lParam: Longint): Longint; export;
{***
Subclassing routine for the first message box button. It's used to handle WMkeydown messages
so that you can tab through the buttons. Basically you only need to subclass when a window
or dialog control needs to handle its own messages. All messages pass through this function.
You just add the messages you want to handle to the case statement and pass the rest onto
the parent window using CallWindowProc. OldProc1 is a pointer to the parent's window procedure
that handles all the parent messages.
***}
begin
MsgBoxButton1Proc := 0;
case Message of
wm_KeyDown : MsgboxKeyDown(MsgBoxWnd, Wnd, wParam);
end;
MsgBoxButton1Proc := CallWindowProc (OldProc1, Wnd, Message, wParam, lParam);
end;
function MsgBoxButton2Proc (Wnd: HWnd; Message, wParam: Word; lParam: Longint): Longint; export;
{*** Subclassing routine for the second message box button ***}
begin
MsgBoxButton2Proc := 0;
case Message of
wm_KeyDown : MsgboxKeyDown(MsgBoxWnd, Wnd, wParam);
end;
MsgBoxButton2Proc := CallWindowProc (OldProc2, Wnd, Message, wParam, lParam);
end;
function MsgBoxButton3Proc (Wnd: HWnd; Message, wParam: Word; lParam: Longint): Longint; export;
{*** Subclassing routine for the third message box button ***}
begin
MsgBoxButton3Proc := 0;
case Message of
wm_KeyDown : MsgboxKeyDown(MsgBoxWnd, Wnd, wParam);
end;
MsgBoxButton3Proc := CallWindowProc (OldProc3, Wnd, Message, wParam, lParam);
end;
function MsgBoxProc(Wnd: HWnd; Message, wParam: Word; lParam: Longint): Longint; export;
{***
MsgBoxProc is the callback procedure that handles all the messages for the message box
window. It works the same as for the buttons except because it's the parent it passes
the messages it doesn't handle onto DefWindowProc. This includes any child messages
returned to it. This function is called a Window Procedure (WindowProc) and it can have
any name you want. The window procdure is assigned to a window class in a TWndClass
structure. All windows created with the same class use the same window procdure. Any
children that need to handle their own messages must be subclassed. This can be done in
a wm_Create method added to the case statement but I found it better to do it in the
main window procedure 'MsgBoxWinMain' (WinMain).
***}
type
NCRect = array[0..2] of TRect;
PRect = ^NCRect;
var
MinMaxInfo : PMinMaxInfo;
begin
MsgBoxProc := 0;
case Message of
wm_Destroy:
begin
if HLib >= 32 then FreeLibrary(HLib);
if BkBmp <> 0 then
begin
DeleteObject(BkBmp);
DeleteObject(BkBrush);
end;
if MsgBmp <> 0 then DeleteObject(MsgBmp);
if UpBmp1 <> 0 then DeleteObject(UpBmp1);
if UpBmp2 <> 0 then DeleteObject(UpBmp2);
if UpBmp3 <> 0 then DeleteObject(UpBmp3);
{***
PostQuitMessage send a wm_Quit message to the window so it exits the GetMessage
message loop in the MsgBoxWinMain procedure.
***}
PostQuitMessage(0);
Exit;
end;
wm_Paint:
begin
PaintMsgBox (Wnd, szText, a, e, f, MsgBmp, SFXStyle);
if SFXStyle then DrawSFXFrame(Wnd);
end;
wm_DrawItem: DrawMsgBoxButton(Wnd, lParam);
wm_Command:
begin
{***
There are no Msg.lParam Hi's or Lo's in TMsg so you have to use HiWord/LoWord.
When a button is clicked 'Reply' is the return value passed back to the message box
function. LastWnd (WndParent from the message box function) is enabled and is given
the focus. DestroyWindow sends a wm_Destroy message (which is handled above) to the
window and lastly the window is unregistered. I need to unregister the window because
there are four possible registrations and I don't know which style of messagebox will
be registered next. You might use more than one type in a program as I did in the
MDITool sample.
***}
if HiWord(lParam) = bn_Clicked then
begin
Reply := wParam;
EnableWindow(LastWnd, True);
SetFocus(LastWnd);
DestroyWindow(Wnd);
if SFXStyle then
UnregisterClass('SFXMsgBoxWindow', SFXWndHdl)
else
UnregisterClass('MWCCMsgBoxWindow', MWCCWndHdl);
end;
end;
wm_NCPaint:
begin
if SFXStyle then
begin
DrawSFXFrame(Wnd);
GetWindowText(Wnd, szTitle, sizeof(szTitle));
SetWindowText(Wnd, szTitle);
{***
MsgBoxProc := 1 is the same as Msg.Result := 1 in an OWL program.
It is the return value for the message.
***}
MsgBoxProc := 1;
{***
If you want to override the default message behaviour then don't pass the message
onto DefWindowProc - just Exit.
***}
Exit;
end;
end;
wm_NCCalcSize: if SFXStyle then Inc(PRect(lParam)^[0].Top, 1);
wm_Activate: if SFXStyle then DrawSFXFrame(Wnd);
wm_NCActivate: if SFXStyle then DrawSFXFrame(Wnd);
wm_ActivateApp: if SFXStyle then DrawSFXFrame(Wnd);
wm_GetMinMaxInfo:
begin
longInt(MinMaxInfo) := lParam;
GetWindowRect(Wnd, WinRect);
if ((WinRect.Right-WinRect.Left) > 36) and ((WinRect.Bottom-WinRect.Top) > 36) then
begin
MinMaxInfo^[1].X := WinRect.Right - WinRect.Left;
MinMaxInfo^[1].Y := WinRect.Bottom - WinRect.Top;
MinMaxInfo^[3].X := WinRect.Right - WinRect.Left;
MinMaxInfo^[3].Y := WinRect.Bottom - WinRect.Top;
MinMaxInfo^[4].X := WinRect.Right - WinRect.Left;
MinMaxInfo^[4].Y := WinRect.Bottom - WinRect.Top;
end;
end;
end;
{*** Passes all messages that reach this point onto DefWindowProc ***}
MsgBoxProc := DefWindowProc(Wnd, Message, wParam, lParam);
end;
procedure MsgBoxWinMain (WndParent: HWnd; ATxt, ACaption: PChar; ATextType: Word; ABmp: PChar);
{*** WinMain Window function
WinMain is not defined in Pascal so you can call this procedure anything you like and give
it any parameters. One thing to remember - to make the window appear as fast as possible
initialize everything you can before you actually create the mainwindow.
***}
label
CaseExit;
const
{*** Class Sructure for MWCCMsgBox ***}
MWCCWndClass : TWndClass = (style : 0;
lpfnWndProc : @MsgBoxProc; {MsgBoxProc Window Procedure}
cbClsExtra : 0;
cbWndExtra : 0;
hInstance : 0;
hIcon : 0;
hCursor : 0;
hbrBackground : 0;
lpszMenuName : nil;
lpszClassName : 'MWCCMsgBoxWindow');
{*** Class Sructure for SFXMsgBox ***}
SFXWndClass : TWndClass = (style : 0;
lpfnWndProc : @MsgBoxProc; {Uses the same Window Procedure}
cbClsExtra : 0;
cbWndExtra : 0;
hInstance : 0;
hIcon : 0;
hCursor : 0;
hbrBackground : 0;
lpszMenuName : nil;
lpszClassName : 'SFXMsgBoxWindow');
var
SysMenu : HMenu;
FocusWnd : HWnd;
W : Integer;
H : Integer;
XScreen : Integer;
YScreen : Integer;
Msg : TMsg;
{*** Loads the big message bitmaps ***}
procedure LoadBmp (wBmp: Word);
begin
if wBmp = 0 then MsgBmp := 0;
if wBmp = 16 then MsgBmp := LoadBitmap(HLib, PChar(1901));
if wBmp = 32 then MsgBmp := LoadBitmap(HLib, PChar(1902));
if wBmp = 48 then MsgBmp := LoadBitmap(HLib, PChar(1903));
if wBmp = 64 then MsgBmp := LoadBitmap(HLib, PChar(1904));
end;
begin
HLib := LoadLibrary ('MWCC.dll');
if HPrevInst = 0 then
begin
{***
This registers the class - I need to register two. You don't need to register the class
if its already registered so check HPrevInst.
***}
if SFXStyle then
begin
SFXWndClass.hInstance := HInstance;
SFXWndClass.hCursor := LoadCursor(0, idc_Arrow);
SFXWndClass.hbrBackground := GetStockObject(LtGray_Brush);
{*** This handle is used to unregistered the class when the message box is destroyed ***}
SFXWndHdl := HInstance;
if not RegisterClass(SFXWndClass) then Halt(255);
end
else
begin
MWCCWndClass.hInstance := HInstance;
MWCCWndClass.hCursor := LoadCursor(0, idc_Arrow);
if ABmp <> nil then
begin
BkBmp := LoadBitmap(HLib, ABmp);
BkBrush := CreatePatternBrush(BkBmp);
MWCCWndClass.hbrBackground := BkBrush;
end
else
MWCCWndClass.hbrBackground := GetStockObject(LtGray_Brush);
{*** This handle is used to unregistered the class when the message box is destroyed ***}
MWCCWndHdl := HInstance;
if not RegisterClass(MWCCWndClass) then Halt(255);
end;
end;
{***
ATextType falls within these values when mb_SystemModal is specified, in which case
it's passed onto the Windows API MessageBox function.
***}
if (ATextType >= 4096) and (ATextType < 8192) then
begin
MessageBox(0, ATxt, ACaption, ATextType);
Halt;
end;
if GetSystemMetrics(sm_CYSize) = 26 then
begin
a := 80; b := 40; c := 27; d := 20;
end;
LastWnd := WndParent;
lstrCpy(szText, ATxt);
{***
This long bit sorts out the values passed in ATextType and initializes the appropriate
things.
***}
if ATextType >= 8192 then
ATextType := ATextType - 8192
else
if (ATextType >= 512) and (ATextType < 4096) then
begin
Default3 := True;
ATextType := ATextType - 512;
end
else
if (ATextType >= 256) and (ATextType < 512) then
begin
Default2 := True;
ATextType := ATextType - 256;
end
else
Default1 := True;
case ATextType of
0, 64, 48, 16, 32:
begin
ID1 := id_Ok;
LoadBmp(ATextType);
goto CaseExit;
end;
1, 65, 49, 17, 33:
begin
ID1 := id_Ok; ID2 := id_Cancel;
LoadBmp(ATextType - 1);
goto CaseExit;
end;
5, 69, 53, 21, 37:
begin
ID1 := id_Retry; ID2 := id_Cancel;
LoadBmp(ATextType - 5);
goto CaseExit;
end;
4, 68, 52, 20, 36:
begin
ID1 := id_Yes; ID2 := id_No;
LoadBmp(ATextType - 4);
goto CaseExit;
end;
3, 67, 51, 19, 35:
begin
ID1 := id_Yes; ID2 := id_No; ID3 := id_Cancel;
LoadBmp(ATextType - 3);
goto CaseExit;
end;
2, 66, 50, 18, 34:
begin
ID1 := id_Abort; ID2 := id_Retry; ID3 := id_Ignore;
LoadBmp(ATextType - 2);
goto CaseExit;
end;
{*** AtextType ends here ***}
end;
CaseExit:
{*** Loads the up bitmaps needed to speed up the initial drawing of the buttons ***}
if ID1 <> 0 then if not Default1 then
UpBmp1 := LoadBitmap(HLib, PChar(1000 + ID1))
else
UpBmp1 := LoadBitmap(HLib, PChar(5000 + ID1));
if ID2 <> 0 then if not Default2 then
UpBmp2 := LoadBitmap(HLib, PChar(1000 + ID1))
else
UpBmp2 := LoadBitmap(HLib, PChar(5000 + ID1));
if ID3 <> 0 then if not Default3 then
UpBmp3 := LoadBitmap(HLib, PChar(1000 + ID1))
else
UpBmp3 := LoadBitmap(HLib, PChar(5000 + ID1));
XScreen := GetSystemMetrics(sm_CXScreen);
YScreen := GetSystemMetrics(sm_CYScreen);
W := 388 + GetSystemMetrics(sm_CXFrame) + a - e;
H := 220 + GetSystemMetrics(sm_CYCaption) + GetSystemMetrics(sm_CYFrame) - f;
{*** Creates an SFX message box window if the SFXMsgbox function is used ***}
if SFXStyle then
MsgBoxWnd := CreateWindow('SFXMsgBoxWindow',
ACaption,
ws_Popup or ws_Caption or ws_SysMenu or ws_ThickFrame,
(XScreen - W) div 2,
(YScreen - H) div 2,
W, H, 0, 0,
HInstance,
nil)
else
{*** Creates an MWCC message box window if the MWCCMsgbox function is used ***}
MsgBoxWnd := CreateWindowEx(ws_Ex_DlgModalFrame,
'MWCCMsgBoxWindow',
ACaption,
ws_Popup or ws_Caption or ws_SysMenu,
(XScreen - W) div 2,
(YScreen - H) div 2,
W, H, 0, 0,
HInstance,
nil);
{***
Subclassing the Buttons has three parts - MakeProcInstance, CreateWindow and
SetWindowLong. Subclassing a dialog is slightly diffent. See the generic demo
generic.pas that came with your complier.
I only subclass the buttons that are actually used - so hence all the <>'s
***}
if ID1 <> 0 then
ButtonProc1 := MakeProcInstance(@MsgBoxButton1Proc, HInstance);
if ID2 <> 0 then
ButtonProc2 := MakeProcInstance(@MsgBoxButton2Proc, HInstance);
if ID3 <> 0 then
ButtonProc3 := MakeProcInstance(@MsgBoxButton3Proc, HInstance);
if (ID1 <> 0) and (ID2 = 0) and (ID3 = 0) then
begin
WndButton1 := CreateWindow('Button', nil, ws_Child or ws_Visible or ws_TabStop or
bs_OwnerDraw, 156 + b - (e div 2), 142, 74, 54, MsgBoxWnd, ID1,
HInstance, nil);
end
else
if (ID1 <> 0) and (ID2 <> 0) and (ID3 = 0) then
begin
WndButton1 := CreateWindow('Button', nil, ws_Child or ws_Visible or ws_TabStop or
bs_OwnerDraw, 78 + c - (e div 2), 142, 74, 54, MsgBoxWnd, ID1,
HInstance, nil);
WndButton2 := CreateWindow('Button', nil, ws_Child or ws_Visible or ws_TabStop or
bs_OwnerDraw, 232 + c * 2 - (e div 2), 142, 74, 54, MsgBoxWnd,
ID2, HInstance, nil);
end
else
if (ID1 <> 0) and (ID2 <> 0) and (ID3 <> 0) then
begin
WndButton1 := CreateWindow('Button', nil, ws_Child or ws_Visible or ws_TabStop or
bs_OwnerDraw, 39 + d - (e div 2), 142, 74, 54, MsgBoxWnd, ID1,
HInstance, nil);
WndButton2 := CreateWindow('Button', nil, ws_Child or ws_Visible or ws_TabStop or
bs_OwnerDraw, 155 + d * 2 - (e div 2), 142, 74, 54, MsgBoxWnd,
ID2, HInstance, nil);
WndButton3 := CreateWindow('Button', nil, ws_Child or ws_Visible or ws_TabStop or
bs_OwnerDraw, 270 + d * 3 - (e div 2), 142, 74, 54, MsgBoxWnd,
ID3, HInstance, nil);
end;
{***
OldProc1 etc is a pointer to the parent (old) window procdure return by
SetWindowLong. It's used by the subclassed children to pass messages back to the parent.
***}
if ID1 <> 0 then
LongInt(OldProc1) := SetWindowLong(WndButton1, gwl_WndProc, LongInt(ButtonProc1));
if ID2 <> 0 then
LongInt(OldProc2) := SetWindowLong(WndButton2, gwl_WndProc, LongInt(ButtonProc2));
if ID3 <> 0 then
LongInt(OldProc3) := SetWindowLong(WndButton3, gwl_WndProc, LongInt(ButtonProc3));
{*** Focuses which ever button is the default ***}
if Default1 = True then
FocusWnd := WndButton1
else
if Default2 = True then
FocusWnd := WndButton2
else
if Default3 = True then
FocusWnd := WndButton3;
SetFocus(FocusWnd);
InvalidateRect(FocusWnd, nil, True);
{*** System Menu Changes ***}
SysMenu := GetSystemMenu(MsgBoxWnd, False);
DeleteMenu(SysMenu, 0, mf_ByPosition);
DeleteMenu(SysMenu, 1, mf_ByPosition);
DeleteMenu(SysMenu, 1, mf_ByPosition);
DeleteMenu(SysMenu, 1, mf_ByPosition);
DeleteMenu(SysMenu, 1, mf_ByPosition);
DeleteMenu(SysMenu, 2, mf_ByPosition);
DeleteMenu(SysMenu, 2, mf_ByPosition);
DeleteMenu(SysMenu, 1, mf_ByPosition);
{*** Show and Update the message box window so it gets painted ***}
ShowWindow(MsgBoxWnd, sw_ShowNormal);
UpdateWindow(MsgBoxWnd);
{***
The message box disables LastWnd (WndParent) so it can't be used until the message
box is destroyed.
***}
EnableWindow(LastWnd, False);
{***
Now that everything is initalized the window enters its message loop and stays there
until you call 'PostQuitMessage' (in wm_Destroy) - which does just that and the window
exits the loop.
***}
while GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
function MWCCMsgBox (WndParent: HWnd; ATxt, ACaption: PChar; ATextType: Word;
ABmp: PChar): Integer;
{*** The other end of the MWCCMsgBox function used in your source code ***}
begin
InitializeData;
MsgBoxWinMain (WndParent, ATxt, ACaption, ATextType, ABmp);
MWCCMsgBox := Reply;
InitializeData;
end;
function SFXMsgBox (WndParent: HWnd; ATxt, ACaption: PChar; ATextType: Word): Integer;
{*** The other end of the SFXMsgBox function used in your source code ***}
begin
InitializeData;
{***
SFXStyle tells the program to draw an SFX style message box. 'e' and 'f' are offsets
used throughout the program to adjust the message box dimensions and produce the
slightly smaller SFX message box.
***}
SFXStyle := True;
e := 12; f := 1;
MsgBoxWinMain (WndParent, ATxt, ACaption, ATextType, nil);
SFXMsgBox := Reply;
InitializeData;
end;
end.